/********************************************************************************
 * Copyright (c)2016-2020, ShenZhen WanJiaAn Technology CO.,LTD.
 * All Rights Reserved.
 *
 * File Name     : Color2Grey.c
 * Author        : joki.zhu
 * Date          : 2019-11-14
 *
 * Record        :
 * 1.Date        : 2019-11-14
 *   Author      : joki.zhu
 *   Modification: Created file
 ********************************************************************************/
#include "Color2Grey.h"
#include "app_common.h"
#include "Video.h"
#include "ProductManager.h"

#define DAYNIGHT_ADC_CHN        (1)
#define DAYNIGHT_ADC_DET_NUM    (20)

typedef struct {
    int adcChn;
    int adcDetAverageNum;
    int adcMaxValue;
    int adcMinValue;
}DAYNIGHT_ADC_INFO_S;

typedef struct {
    char bAdcEnable;
    DAYNIGHT_ADC_INFO_S stAdcInfo;
    DAYNIGHT_MODE_E enDayNightMode;
    IR_NIGHT_MODE_E enIrNightMode;
    pthread_t color2greyPid;
}DAYNIGHT_ATTR_S;

static DAYNIGHT_ATTR_S gs_stDayNightAttr;

static int IrLedSet(char bOpen)
{
    int ret = 0;

    if (bOpen == 1)
    {
        ret = GpioSet(PRODUCT_GPIO_INFRAREDLAMP);
        if (ret < 0) {
            LOGE("GpioSet PRODUCT_GPIO_INFRAREDLAMP failed\n");
            return -1;
        }
    }
    else
    {
        ret = GpioReset(PRODUCT_GPIO_INFRAREDLAMP);
        if (ret < 0) {
            LOGE("GpioReset PRODUCT_GPIO_INFRAREDLAMP failed\n");
            return -1;
        }        
    }

    return 0;
}

static int IrCutSet(char bOpen)
{
    int ret = 0;

    if (PRODUCT_MODEL_B1 == ProductGetHandle()->ProductModel) 
    {
        if (bOpen == 1) {
            ret = GpioSet(PRODUCT_GPIO_IRCUT0);
            if (ret < 0) {
                LOGE("GpioSet PRODUCT_GPIO_IRCUT0 failed\n");
                return -1;
            }
        } else {
            ret = GpioReset(PRODUCT_GPIO_IRCUT0);
            if (ret < 0) {
                LOGE("GpioReset PRODUCT_GPIO_IRCUT0 failed\n");
                return -1;
            }
        }
    } 
    else if (PRODUCT_MODEL_B5 == ProductGetHandle()->ProductModel) 
    {
        if (bOpen == 1) {
            ret = GpioReset(PRODUCT_GPIO_IRCUT0);
            if (ret < 0) {
                LOGE("GpioSet PRODUCT_GPIO_IRCUT0 failed\n");
                return -1;
            }
            
            ret = GpioSet(PRODUCT_GPIO_IRCUT1);
            if (ret < 0) {
                LOGE("GpioSet PRODUCT_GPIO_IRCUT1 failed\n");
                return -1;
            }
        } else {
            ret = GpioSet(PRODUCT_GPIO_IRCUT0);
            if (ret < 0) {
                LOGE("GpioReset PRODUCT_GPIO_IRCUT0 failed\n");
                return -1;
            }

            ret = GpioReset(PRODUCT_GPIO_IRCUT1);
            if (ret < 0) {
                LOGE("GpioSet PRODUCT_GPIO_IRCUT1 failed\n");
                return -1;
            }
        }
        
        usleep(100 * 1000);
        ret = GpioSet(PRODUCT_GPIO_IRCUT0);
        if (ret < 0) {
            LOGE("GpioReset PRODUCT_GPIO_IRCUT0 failed\n");
            return -1;
        }
        
        ret = GpioSet(PRODUCT_GPIO_IRCUT1);
        if (ret < 0) {
            LOGE("GpioSet PRODUCT_GPIO_IRCUT1 failed\n");
            return -1;
        }
    }

    return 0;
}

static int DayNightModeSet(DAYNIGHT_MODE_E enDayNightMode)
{
    if (enDayNightMode < NIGHT_MODE || enDayNightMode >= DAYNIGHT_MODE_NONE) {
        LOGE("enDayNightMode %d invalied\n", enDayNightMode);
        return -1;
    }

    int ret = 0;
    
    switch (enDayNightMode)
    {
        case NIGHT_MODE:
            ret = VideoGetOpsHandle()->set_daynight_mode(0, VIDEO_NIGHT_ON);
            if (ret < 0) {
                LOGE("set_daynight_mode failed\n");
                return -1;
            }
            if (PRODUCT_MODEL_B5 == ProductGetHandle()->ProductModel) {
                if (gs_stDayNightAttr.enDayNightMode != DAYNIGHT_MODE_NONE) {
                    sleep(3);
                }
            } else {
                usleep(500 * 1000);
            }
            
            IrLedSet(1);
            IrCutSet(0);
            break;
        case DAY_MODE:
            ret = VideoGetOpsHandle()->set_daynight_mode(0, VIDEO_NIGHT_OFF);
            if (ret < 0) {
                LOGE("set_daynight_mode failed\n");
                return -1;
            }
            IrLedSet(0);
            IrCutSet(1);        
            break;
        default:
            break;
    }

    gs_stDayNightAttr.enDayNightMode = enDayNightMode;
    
    return 0;
}

static DAYNIGHT_MODE_E DayNightAdc2Mode(void)
{
    int i = 0;
    int ret = 0;
    int adcValue = 0;
    int adcTotalValue = 0;
    int adcAvgValue = 0;
    DAYNIGHT_MODE_E enMode = DAYNIGHT_MODE_NONE;

    for (i = 0; i < gs_stDayNightAttr.stAdcInfo.adcDetAverageNum; i++)
    {
        adcValue = 0;
        ret = AdcGetVal(gs_stDayNightAttr.stAdcInfo.adcChn, &adcValue);
        if (ret < 0) {
            LOGE("AdcGetVal failed\n");
            return -1;
        }
        adcTotalValue += adcValue;
    }

    adcAvgValue = adcTotalValue / gs_stDayNightAttr.stAdcInfo.adcDetAverageNum;
    LOGD("adcAvgValue : %d\n", adcAvgValue);
    
    if (adcAvgValue > gs_stDayNightAttr.stAdcInfo.adcMaxValue)
    {
        enMode = DAY_MODE;
    }
    else if (adcAvgValue < gs_stDayNightAttr.stAdcInfo.adcMinValue)
    {
        enMode = NIGHT_MODE;
    }
    
    return enMode;
}

static int DayNightSwitch(void)
{
    int ret = 0;
    DAYNIGHT_MODE_E enMode = DAYNIGHT_MODE_NONE;

    if (gs_stDayNightAttr.bAdcEnable == 1) {
        enMode = DayNightAdc2Mode();
    }
    
    if ((enMode != DAYNIGHT_MODE_NONE) && (enMode != gs_stDayNightAttr.enDayNightMode))
    {
        switch (enMode)
        {
            case NIGHT_MODE:
                ret = DayNightModeSet(NIGHT_MODE);
                if (ret < 0) {
                    LOGE("DayNightModeSet NIGHT_MODE failed\n");
                }
                break;
            case DAY_MODE:
                ret = DayNightModeSet(DAY_MODE);
                if (ret < 0) {
                    LOGE("DayNightModeSet DAY_MODE failed\n");
                }
                break;
            default:
                LOGW("DayNight enMode is invalid\n");
                break;
        }
    }

    return 0;
}

void *tskColor2Grey(void *args)
{
    int ret = 0;
    IR_NIGHT_MODE_E enIrNightMode = IR_NIGHT_MODE_NONE;
    
    SET_THREAD_NAME("tskColor2Grey");
    pthread_detach(pthread_self());

    /* set default ir night mode */
    char uuid[32] = "";
    DevConfigGetUuid(uuid, sizeof(uuid));
    if (strlen(uuid) <= 1) {
        DevConfigSetIrNightMode(2);
    }

    /* init day night mode from cfg */
    int irNightMode = 0;
    DAYNIGHT_MODE_E enDayNightMode = DAYNIGHT_MODE_NONE;

    DevConfigGetIrNightMode(&irNightMode);
    switch (irNightMode)
    {
        case IR_NIGHT_OFF:
            enDayNightMode = DAY_MODE;
            break;
        case IR_NIGHT_ON:
            enDayNightMode = NIGHT_MODE;
            break;
        case IR_NIGHT_AUTO:
        default:
            enDayNightMode = DAY_MODE;
            break;
    }
    
#ifdef ZDK_PROTOCOL
    enIrNightMode = IR_NIGHT_OFF;
#endif /* ZDK_PROTOCOL */
    Color2GreySetMode(enDayNightMode);
    gs_stDayNightAttr.enIrNightMode = irNightMode;
    
    while (1)
    {
        enIrNightMode = Color2GreyGetIrNightMode();
#ifdef ZDK_PROTOCOL
        enIrNightMode = IR_NIGHT_AUTO;
#endif /* ZDK_PROTOCOL */

        if (enIrNightMode == IR_NIGHT_AUTO)
        {
            ret = DayNightSwitch();
            if (ret < 0) {
                LOGE("DayNightSwitch failed\n");
                usleep(100 * 1000);
                continue;
            }
        }
        
        sleep(1);
    }
    
    pthread_exit(0);
}

DAYNIGHT_MODE_E Color2GreyGetState(void)
{
    return gs_stDayNightAttr.enDayNightMode;
}

int Color2GreySetMode(DAYNIGHT_MODE_E enDayNightMode)
{
    if (enDayNightMode < NIGHT_MODE || enDayNightMode >= DAYNIGHT_MODE_NONE) {
        LOGE("enDayNightMode %d invalied\n", enDayNightMode);
        return -1;
    }

    int ret = 0;

    ret = DayNightModeSet(enDayNightMode);
    if (ret < 0) {
        LOGE("DayNightModeSet NIGHT_MODE failed\n");
    }    

    return 0;
}

int Color2GreySetIrNightMode(IR_NIGHT_MODE_E enIrNightMode)
{
    switch (enIrNightMode)
    {
        case IR_NIGHT_OFF:
            Color2GreySetMode(DAY_MODE);
            break;
        case IR_NIGHT_ON:
            Color2GreySetMode(NIGHT_MODE);
            break;
        case IR_NIGHT_AUTO:
            break;
        default:
            LOGW("enIrNightMode %d is invalid\n", enIrNightMode);
            return -1;
    }

    gs_stDayNightAttr.enIrNightMode = enIrNightMode;

    return 0;
}

IR_NIGHT_MODE_E Color2GreyGetIrNightMode(void)
{
    return gs_stDayNightAttr.enIrNightMode;
}

int Color2GreyInit(void)
{
#ifdef MINI_APP
    return 0;
#endif /* MINI_APP */

    int ret = 0;
    pthread_t color2greyPid = 0;
    
    memset(&gs_stDayNightAttr, 0, sizeof(gs_stDayNightAttr));
    gs_stDayNightAttr.bAdcEnable = ProductGetHandle()->bAdcPhotoresistance;
    gs_stDayNightAttr.stAdcInfo.adcChn = DAYNIGHT_ADC_CHN;
    gs_stDayNightAttr.stAdcInfo.adcDetAverageNum = DAYNIGHT_ADC_DET_NUM;

    char hwVersion[32] = "";
    DevConfigGetHardVersion(hwVersion, sizeof(hwVersion));
    if (strncmp(hwVersion, "B1-MAIN-V11", sizeof(hwVersion)) == 0) {
        gs_stDayNightAttr.stAdcInfo.adcMaxValue = 300;
        gs_stDayNightAttr.stAdcInfo.adcMinValue = 100;
    } else {
        gs_stDayNightAttr.stAdcInfo.adcMaxValue = ProductGetHandle()->AdcMaxValue;
        gs_stDayNightAttr.stAdcInfo.adcMinValue = ProductGetHandle()->AdcMinValue;
    }
    gs_stDayNightAttr.enDayNightMode = DAYNIGHT_MODE_NONE;
    gs_stDayNightAttr.enIrNightMode = IR_NIGHT_OFF;
    gs_stDayNightAttr.color2greyPid = 0;
    
    ret = pthread_create(&gs_stDayNightAttr.color2greyPid, 0, (void *)tskColor2Grey, NULL);
    if (ret != 0) {
        LOGE("pthread_create tskColor2Grey failed\n");
        return -1;
    }


    return 0;
}


int Color2GreyDeinit(void)
{
    pthread_cancel(gs_stDayNightAttr.color2greyPid);
    
    return 0;
}

